/*
 * cx_escape_str.c
 *
 *  Created on: 2010-3-11
 *      Author: raycchen
 */
#include "cx_platforms.h"
#include "cx_typedef.h"
#include "cx_memory.h"
#include "../inc/cx_escape_str.h"
#include "../cx_http/CoderFactory.h"

/* for ucs2 to utf8 *********************************/
#define CAST_CPU8(RAW)  ((const unsigned char *)(RAW))

#define GET_U8_BYTE_TO_U16(RAW, i)  ((unsigned short int)(CAST_CPU8(RAW)[i]))

#define STR_SIZE(len) ((len)<<1)

#define CHR_AT(RAW, n) ((unsigned short int)(GET_U8_BYTE_TO_U16(RAW, STR_SIZE(n))+(GET_U8_BYTE_TO_U16(RAW, STR_SIZE(n)+1)<<8)))
/* for ucs2 to utf8 *********************************/

const unsigned long __bpc[16] =
{
	1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 0
};


 QBOOL  cx_escapeStrConvert(CONST IN QCHAR *pSrc, CONST QINT nSrcSize, QBOOL bKeepSpace, OUT QCHAR** ppDest, OUT QINT *pnDestSize)
 {
	 return ConvertFormatChar((QCHAR*)pSrc, nSrcSize, bKeepSpace, ppDest, pnDestSize);
 }

 QCHAR* cx_convertvaluedata(QCHAR* pChar,QINT len)
{
	if(NULL == pChar || len < 0)
		return NULL;
	
	return ConvertValueData(pChar,len);
}

 void cx_ucs2_to_utf8_string(unsigned char *dest,int dest_size,unsigned char * src)
 {
 	unsigned int src_end_pos = (unsigned int) src;

 	ucs2_to_utf8_sting(dest, dest_size, src, &src_end_pos);
 }


 /* for ucs2 to utf8 */
 int ucs2_to_utf8_chset(unsigned char *utf8,unsigned short int ucs2)
 {
     int count;
 	
     if (ucs2 < (unsigned short int) 0x80)
     {
         count = 1;
     }
     else if (ucs2 < (unsigned short int) 0x800)
     {
         count = 2;
     }
     else
     {
         count = 3;
     }
     switch (count)
     {
 	case 3:
 		utf8[2] = 0x80 | (ucs2 & 0x3f);
 		ucs2 = ucs2 >> 6;
 		ucs2 |= 0x800;
 	case 2:
 		utf8[1] = 0x80 | (ucs2 & 0x3f);
 		ucs2 = ucs2 >> 6;
 		ucs2 |= 0xc0;
 	case 1:
 		utf8[0] = (unsigned char) ucs2;
     }
     return count;
 }

 int ucs2_to_utf8_chset_len(unsigned short int ucs2)
 {
     if (ucs2 < (unsigned short int) 0x80)
     {
         return 1;
     }
     else if (ucs2 < (unsigned short int) 0x800)
     {
         return 2;
     }
     else
     {
         return 3;
     }
 }

 int ucs2_to_utf8_sting(unsigned char * dest,int dest_size,unsigned char *src,unsigned int * src_end_pos)
 {
     int pos = 0;
 	
     while (src[0] || src[1])
     {
         if (pos + ucs2_to_utf8_chset_len(CHR_AT(src, 0)) >= dest_size)      /* leave space of '\0' */
         {
             break;
         }
 		
         pos += ucs2_to_utf8_chset(dest + pos, CHR_AT(src, 0));
         src += 2;
         if (pos >= dest_size - 1)
         {
             break;
         }
     }
     if (pos >= dest_size)
     {
         dest[dest_size - 1] = 0;
     }
     else
     {
         dest[pos] = 0;
     }
     *src_end_pos = (unsigned int) src;
     return pos + 1;
 }
 
 

 int copy_string_w(unsigned short ** pDst,unsigned short* pSrc)
 {
 	int size;
 	if(!pDst || !pSrc)
 		return 0;

 	if(*pDst)
 		cx_free(*pDst);

 	size = (cx_strlen_w(pSrc)+1)*2;

 	*pDst = NULL;
 	*pDst = (unsigned short*)cx_malloc(size);
 	if(*pDst == NULL)
 		return 0;

 	cx_memset(*pDst,0,size);
 	cx_strcpy_w(*pDst,pSrc);
 	return 1;
 }
 
 int copy_stringn_w(unsigned short ** pDst,unsigned short* pSrc,int count)
 {
 	int size;
 	if(!pDst || !pSrc)
 		return 0;

 	if(*pDst)
 		cx_free(*pDst);

 	size = (/*cx_strlen_w(pSrc)*/count+1)*2;

 	*pDst = NULL;
 	*pDst = (unsigned short*)cx_malloc(size);
 	if(*pDst == NULL)
 		return 0;

 	cx_memset(*pDst,0,size);
 	cx_strncpy_w(*pDst,pSrc,count);
 	//cx_strcpy_w(*pDst,pSrc);
 	return 1;
 }

 int convert_url_to_utf8(char ** pDst,unsigned short* pSrc)
 {
 	int url_len = 0;
 	char* dst_url;
 	int len;
 	if(!pDst || !pSrc)
 		return 0;

 	if(*pDst)
 		cx_free(*pDst);

 	//char* url_normal = NULL;
 	*pDst = NULL;
 	url_len = 0;

 	len = cx_strlen_w((CONST QWCHAR*)pSrc);
 	dst_url = (char *)cx_malloc(UTF8_ENCODING_LENGTH*(len + 1));
 	if(NULL == dst_url)
 		return 0;
 	cx_memset(dst_url,0,UTF8_ENCODING_LENGTH*(len + 1));
 	cx_ucs2_to_utf8_string((unsigned char *)dst_url,UTF8_ENCODING_LENGTH*(len + 1),(unsigned char *)pSrc);

 	cx_escapeStrConvert((const char*)dst_url,strlen((const char *)dst_url),QFALSE,(char **)pDst,&url_len);
 	cx_free(dst_url);
 	return 1;
 }


 unsigned long cx_utf8_to_ucs2_string( void * buff_ptr, unsigned long buff_size, void * utf8_str, unsigned long utf8_len )
 {
 	unsigned long	conv_len = 0;
 	unsigned long	char_cnt = 0;
 	unsigned long	char_bytes;
 	unsigned char *	us_utf8_str = (unsigned char *)utf8_str;
 	unsigned long	i;
 	unsigned short	tmp_ch;

 	if ( NULL == buff_ptr || NULL == us_utf8_str || buff_size < 2 || 0 == utf8_len )
 		return 0;

 	for ( i = 0; i < utf8_len; i += char_bytes )
 	{
 		if ( '\0' == *us_utf8_str )
 			break;

 		char_bytes = __bpc[((unsigned long)*us_utf8_str) >> 4];

 		if ( 1 == char_bytes )
 		{
 			tmp_ch = (unsigned short)us_utf8_str[0];
 		}
 		else if ( 2 == char_bytes )
 		{
 			if ( '\0' != us_utf8_str[1] )
 			{
 				tmp_ch = ((unsigned short)(us_utf8_str[0] & 0x1F) << 6) | ((unsigned short)(us_utf8_str[1] ^ 0x80));
 			}
 		}
 		else if ( 3 == char_bytes )
 		{
 			if ( '\0' != us_utf8_str[1] && '\0' != us_utf8_str[2] )
 			{
 				tmp_ch = ((unsigned short)(us_utf8_str[0] & 0x0F) << 12) |
 					((unsigned short)(us_utf8_str[1] ^ 0x80) << 6) |
 					((unsigned short)(us_utf8_str[2] ^ 0x80));
 			}
 		}
 		else
 		{
 			char_cnt = 0;
 			conv_len = 0;
 			break;
 		}

 		((unsigned short *)buff_ptr)[char_cnt] = tmp_ch;
 		char_cnt += 1;

 		conv_len += 2; // sizeof(unsigned short)
 		us_utf8_str += char_bytes;
 	}

 	((unsigned short *)buff_ptr)[char_cnt] = '\0';

 	return (conv_len >> 1);
 }
